<?php
declare (strict_types=1);

namespace app\admin\controller;

use app\common\model\AdminForm;
use app\common\validate\AdminFormValidate;
use think\exception\ValidateException;
use think\facade\Db;

class Form extends Base
{
    protected $middleware = ['AdminCheck'];

    // 系统配置
    public function index()
    {
        if (request()->isAjax()) {
            return $this->getJson(AdminForm::getList());
        }

       return $this->fetch();
    }

    public function add()
    {
        if (request()->isPost()) {
            $param = input('post.');

            try {
                validate(AdminFormValidate::class)->check($param);
            } catch (ValidateException $e) {
                return jsonReturn(-1, $e->getError());
            }

            // 校验重复
            $hasTitle = AdminForm::where('title', $param['title'])->find();
            if (!empty($hasTitle)) {
                return jsonReturn(-2, '该表单已存在');
            }

            $hasTable = AdminForm::where('table', $param['table'])->find();
            if (!empty($hasTable)) {
                return jsonReturn(-2, '该数据表已存在');
            }

            // 物理上检测表是否存在
            $hasTable = Db::query('SHOW TABLES LIKE "' . config('database.connections.mysql.prefix') . $param['table'] . '"');
            if (!empty($hasTable)) {
                return jsonReturn(-3, '该数据表已存在');
            }

            $param['create_time'] = date('Y-m-d H:i:s');
            try {

                AdminForm::insert($param);
            } catch (\Exception $e) {
                return jsonReturn(-4, $e->getMessage());
            }

            return jsonReturn(0, '添加成功');
        }

        return $this->fetch();
    }

    public function edit()
    {
        if (request()->isPost()) {
            $param = input('post.');

            try {
                validate(AdminFormValidate::class)->check($param);
            } catch (ValidateException $e) {
                return jsonReturn(-1, $e->getError());
            }

            // 校验重复
            $hasTitle = AdminForm::where('title', $param['title'])->where('id', '<>', $param['id'])->find();
            if (!empty($hasTitle)) {
                return jsonReturn(-2, '该表单已存在');
            }

            $hasTable = AdminForm::where('table', $param['table'])->where('id', '<>', $param['id'])->find();
            if (!empty($hasTable)) {
                return jsonReturn(-2, '该数据表已存在');
            }

            // 物理上检测表是否存在
            $oldTableName = AdminForm::where('id', $param['id'])->find();
            $hasTable = Db::query('SHOW TABLES LIKE "' . config('database.connections.mysql.prefix') . $param['table'] . '"');
            if (!empty($hasTable) && $oldTableName['table'] != $param['table']) {
                return jsonReturn(-3, '该数据表已存在');
            }

            $param['update_time'] = date('Y-m-d H:i:s');
            try {

                AdminForm::where('id', $param['id'])->update($param);
            } catch (\Exception $e) {
                return jsonReturn(-4, $e->getMessage());
            }

            return jsonReturn(0, '编辑成功');
        }

        $id = input('param.id');
        $info = AdminForm::where('id', $id)->find();

        return $this->fetch('', [
            'info' => $info
        ]);
    }

    public function del()
    {
        $id = input('post.id');
        $info = AdminForm::where('id', $id)->find();
        if (empty($info)) {
            return jsonReturn(-1, '数据有误');
        }

        if ($info['status'] != 1) {
            return jsonReturn(-2, '不可删除');
        }

        AdminForm::where('id', $id)->delete();

        return jsonReturn(0, '删除成功');
    }

    public function design()
    {
        if (request()->isPost()) {

            $id = input('post.id');
            $param = input('post.data');

            if (empty($param)) {
                return jsonReturn(-1, '所有组件均数据不全，建议您修改后再保存。');
            }

            // 过滤一遍重复的字段
            $fieldMap = [];
            foreach ($param as $key => $vo) {
                // 移除字段为ID 的表单项目
                if (isset($fieldMap[$vo['field']]) || strtolower($vo['field']) == 'id') {
                    unset($param[$key]);
                }

                $fieldMap[$vo['field']] = 1;
            }

            $info = AdminForm::field('now_version')->where('id', $id)->find();
            AdminForm::where('id', $id)->update([
                'now_version' => $info['now_version'] + 1,
                'form_json' => json_encode($param)
            ]);

            return jsonReturn(0, '保存成功');
        }

        $id = input('param.id');
        $info = AdminForm::field('form_json')->where('id', $id)->find();
        if (empty($info['form_json'])) {
            $formJson = [];
        } else {
            $formJson = parseJson(json_decode($info['form_json'], true));
        }


        return $this->fetch('', [
            'id' => $id,
            'data' => empty($formJson) ? '[]' : json_encode($formJson)
        ]);
    }

    public function getAllTables()
    {
        $list = Db::query('SHOW TABLES');

        $data = [];
        foreach ($list as $vo) {
            $data[] = array_values($vo)[0];
        }
        return json(['code' => 0, 'data' => $data, 'msg' => 'success']);
    }

    public function getColumn()
    {
        $list = Db::query('SHOW COLUMNS FROM ' . input('param.table'));
        return json(['code' => 0, 'data' => $list, 'msg' => 'success']);
    }

    public function execSql()
    {
        $options = Db::query(input('param.sql'));
        return json(['code' => 0, 'data' => $options, 'msg' => 'success']);
    }

    // 部署
    public function deploy()
    {
        if (request()->isPost()) {

            $fid = input('param.fid');

            $info = AdminForm::where('id', $fid)->find();

            if (empty($info)) {
                return jsonReturn(-1, '数据有误');
            }

            if (empty($info['form_json'])) {
                return jsonReturn(-2, '请先完成表单设计、设置后再部署');
            }

            if (empty($info['conf_json'])) {
                return jsonReturn(-3, '请先完成设置后再部署');
            }

            try {

                $table = config('database.connections.mysql.prefix') . $info['table'];
                Db::execute('DROP TABLE IF EXISTS `' . $table . '`;');
                // 这里直接覆盖
                $sql = $this->makeTableSql($info);
                Db::execute($sql);
            } catch (\Exception $e) {
                return jsonReturn(-4, $e->getMessage());
            }

            // 判断是否写菜单
            $data = json_decode($info['conf_json'], true);

            $data['left'] = 'flyDesigner';
            $data['right'] = $info['id'];
            (new \app\common\service\AdminPermission())->goMenu($data, 2);

            // 写入钩子event事件文件
            $tpl = root_path() . 'extend' . DS . 'tpl' . DS . 'event.tpl';
            $content = str_replace('{{$name}}', underline_hump($info['table']), file_get_contents($tpl));
            $common = root_path() . 'app' . DS . 'common' . DS . 'flyDesigner';
            @mkdir($common, 0755, true);
            @file_put_contents($common . DS . underline_hump($info['table']) . 'Event.php', $content);

            AdminForm::where('id', $fid)->update([
                'status' => 2
            ]);

            return jsonReturn(0, '部署成功');
        }
    }

    // 卸载
    public function unDeploy()
    {
        if (request()->isPost()) {

            $fid = input('param.fid');
            $info = AdminForm::where('id', $fid)->find();

            if (empty($info)) {
                return jsonReturn(-1, '数据有误');
            }

            if (empty($info['form_json'])) {
                return jsonReturn(-2, '请先完成表单设计、设置后再部署');
            }

            if (empty($info['conf_json'])) {
                return jsonReturn(-3, '请先完成设置后再部署');
            }

            try {

                $table = config('database.connections.mysql.prefix') . $info['table'];
                Db::execute('DROP TABLE IF EXISTS `' . $table . '`;');
            } catch (\Exception $e) {
                return jsonReturn(-4, $e->getMessage());
            }

            // 删除菜单
            $pMenu = (new \app\common\model\AdminPermission)->where('href', '/flyDesigner/index/id/' . $fid)->find();
            (new \app\common\model\AdminPermission)->where('pid', $pMenu['id'])->whereOr('id', $pMenu['id'])->delete();

            // 卸载event
            $file = root_path() . 'app' . DS . 'common' . DS . 'flyDesigner' . DS . underline_hump($info['table']) . 'Event.php';
            @unlink($file);

            AdminForm::where('id', $fid)->update([
                'status' => 1
            ]);

            return jsonReturn(0, '卸载成功');
        }
    }

    /**
     * 生成建表语句
     * @param $info
     * @return string
     */
    protected function makeTableSql($info)
    {
        $column = '';
        $table = config('database.connections.mysql.prefix') . $info['table'];

        $tableJson = json_decode($info['form_json'], true);
        foreach ($tableJson as $key => $vo) {
            // 强迫症为了dd打印的时候格式对其，其实没啥意义
            $tab = '';
            if ($key > 0) {
                $tab = '    ';
            }

            if (in_array($vo['fieldType'], ['int', 'varchar'])) {
                $column .= $tab . '`' . $vo['field'] . '` ' . $vo['fieldType'] . '(' . $vo['fieldLen'] . ') NULL DEFAULT NULL COMMENT "' . $vo['label'] . '",' . PHP_EOL;
            } else {
                $column .= $tab . '`' . $vo['field'] . '` ' . $vo['fieldType'] . ' NULL DEFAULT NULL COMMENT "' . $vo['label'] . '",' . PHP_EOL;
            }
        }

        return <<<EOL
CREATE TABLE `{$table}` (
    `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT "id",
    {$column}    `create_time` datetime NULL DEFAULT NULL COMMENT "创建时间",
    `update_time` datetime NULL DEFAULT NULL COMMENT "更新时间",
    `delete_time` datetime NULL DEFAULT NULL COMMENT "删除时间",
     PRIMARY KEY (`id`) 
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 COMMENT='{$info["title"]}';
EOL;
    }
}